/**
 *
 */
package name.yzhu.wbdata.weibo;

import java.util.List;
import java.util.concurrent.BlockingQueue;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import name.yzhu.common.concurrent.Executable;
import name.yzhu.common.conf.PropertyConfig;
import name.yzhu.common.util.HTMLParse;
import name.yzhu.common.yaml.YamlItem;
import name.yzhu.wbdata.Constant;
import name.yzhu.wbdata.WBDataUtil;

/**
 * @author yhzhu
 *
 */
public abstract class AbstractWeiboSDK implements Executable {
	private static final Log LOG = LogFactory.getLog(AbstractWeiboSDK.class);
	protected WeiboType weiboType ;

	protected String appKey;

	protected String appSecret;

	protected String accessToken;

	protected int publicFreq = 60;

	protected int friendFreq = 180;

	protected int publicCount = 0;

	protected int friendCount = 0;

	protected int skippedPublicRequest = 0;

	protected int skippedFriendRequest = 0;

	protected BlockingQueue<YamlItem> outputQueue = null;

	public abstract void open(PropertyConfig proCFG) ;
	public abstract List<YamlItem> publicTimeLine() throws WeiboException;
	public abstract List<YamlItem> friendTimeLine()  throws WeiboException;
	public abstract String getDataSource();

	protected boolean checkPublicReqest() {
		return true;
	}
	protected boolean checkFriendReqest() {
		return true;
	}

	public AbstractWeiboSDK(BlockingQueue<YamlItem> queue) {
		outputQueue = queue;
	}

	@Override
	public void execute() {
		try {
			if (getPublicFreq() !=0 && ++publicCount >= getPublicFreq()) {
				publicCount = 0;
                try {
                	if (checkPublicReqest()) {
                		skippedPublicRequest = 0;
	                	LOG.info(weiboType.getType()+" begin run public timeline");
	                	long begin = System.currentTimeMillis();
	                	List<YamlItem> yamls = publicTimeLine();
	                	if (yamls != null) {
		                	long end = System.currentTimeMillis();
						    LOG.info(weiboType.getType()+" end run public timeline cost: " + String.valueOf(end - begin));
						    for (YamlItem yaml: yamls){
						    	yaml.put(Constant.YAML_FIELD_WEIBO_TIME_LINE, String.valueOf(Constant.PUBLIC_TIME_LINE_TYPE));
						    	yaml.put(name.yzhu.common.Constant.YAML_FIELD_DATA_SOURCE, getDataSource());
						    	String uuid = WBDataUtil.getUUID(yaml.getString(name.yzhu.common.Constant.YAML_FIELD_DATA_SOURCE),
						    			String.valueOf(yaml.get(Constant.YAML_FIELD_WEIBO_ID)));
						    	yaml.put(name.yzhu.common.Constant.YAML_FIELD_UUID, uuid);
						    	cleanHtml(yaml);
						    	outputQueue.put(yaml);
						    }
	                	}
                	}
                	else {
                		skippedPublicRequest ++;
                		LOG.info(weiboType.getType()+" skipping, check request public timeline");
                	}
                }
                catch(WeiboException e){
                	LOG.error(weiboType.getType()+" run public time line failed", e);
                }
			}

			if (getFriendFreq() !=0 && ++friendCount >= getFriendFreq()) {
				friendCount = 0;
				try {
					if (checkFriendReqest()){
						skippedFriendRequest= 0;
						LOG.info(weiboType.getType()+" begin run friend timeline");
						long begin = System.currentTimeMillis();
						List<YamlItem> yamls = friendTimeLine();
						if (yamls != null) {
							long end = System.currentTimeMillis();
							LOG.info(weiboType.getType()+" end run friend timeline cost: " + String.valueOf(end - begin));
						    for (YamlItem yaml: yamls){
						    	yaml.put(Constant.YAML_FIELD_WEIBO_TIME_LINE, String.valueOf(Constant.FRIEND_TIME_LINE_TYPE));
						    	String uuid = WBDataUtil.getUUID(yaml.getString(name.yzhu.common.Constant.YAML_FIELD_DATA_SOURCE),
						    			String.valueOf(yaml.get(Constant.YAML_FIELD_WEIBO_ID)));
						    	yaml.put(name.yzhu.common.Constant.YAML_FIELD_UUID, uuid);
						    	yaml.put(name.yzhu.common.Constant.YAML_FIELD_DATA_SOURCE, getDataSource());
						    	cleanHtml(yaml);
						    	outputQueue.put(yaml);
						    }
						}
					}
                	else {
                		skippedFriendRequest++;
                		LOG.info(weiboType.getType()+" skipping check friend request friend timeline");
                	}
                }
                catch(WeiboException e){
                	LOG.error(weiboType.getType()+" run friend time line failed", e);
                }
			}
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
		}
	}

	private YamlItem cleanHtml(YamlItem yaml) {
		String txt = HTMLParse.extractText(yaml.getString(name.yzhu.common.Constant.YAML_FIELD_CONTENT));
		yaml.put(name.yzhu.common.Constant.YAML_FIELD_CONTENT, txt);

		txt = HTMLParse.extractText(yaml.getString(name.yzhu.wbdata.Constant.YAML_FIELD_WEIBO_ORIGINAL_TEXT));
		yaml.put(name.yzhu.wbdata.Constant.YAML_FIELD_WEIBO_ORIGINAL_TEXT, txt);

		txt = HTMLParse.extractText(yaml.getString(name.yzhu.wbdata.Constant.YAML_FIELD_WEIBO_SOURCE_NAME));
		yaml.put(name.yzhu.wbdata.Constant.YAML_FIELD_WEIBO_SOURCE_NAME, txt);

		return yaml;
	}

	public String getAppKey() {
		return appKey;
	}

	public void setAppKey(String appKey) {
		this.appKey = appKey;
	}

	public String getAppSecret() {
		return appSecret;
	}

	public void setAppSecret(String appSecret) {
		this.appSecret = appSecret;
	}

	public String getAccessToken() {
		return accessToken;
	}

	public void setAccessToken(String accessToken) {
		this.accessToken = accessToken;
	}

	public void setOutputQueue(BlockingQueue<YamlItem> outputQueue) {
		this.outputQueue = outputQueue;
	}

	public void setPublicFreq(int publicFreq) {
		this.publicFreq = publicFreq;
	}

	public int getPublicFreq() {
		return publicFreq;
	}

	public void setFriendFeq(int friendFreq) {
		this.friendFreq = friendFreq;
	}

	public int getFriendFreq() {
		return friendFreq;
	}

	public WeiboType getWeiboType() {
		return weiboType;
	}
}
